package udptransport;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;

import taxicall.entities.NetworkMessage;

public class UdpNetworkService implements UdpReceiver, UdpSender {
	
	public final static int DEFAULT_PORT = 4000;
	public final static int DEFAULT_BUFFER_SIZE = 4096;

	// for both receiving and sending data
	private DatagramSocket socket;

	// for receiving data
	private byte[] buffer;
	
	public UdpNetworkService() throws SocketException{
		this(DEFAULT_PORT, DEFAULT_BUFFER_SIZE);
	}

	public UdpNetworkService(int portToListen, int receiveBufferSize)
			throws SocketException {
		socket = new DatagramSocket(portToListen);
		buffer = new byte[receiveBufferSize];
	}

	public void send(NetworkMessage msg, InetAddress address, int port) throws IOException {
		byte[] data = SerializationUtils.serialize(msg);
		DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
		socket.send(packet);
	}

	// Blocks
	public DatagramPacket receive() throws IOException {
		return receive(0);
	}

	// Blocks
	public DatagramPacket receive(int timeout) throws IOException {
		DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

		// SocketException will be thrown if we call close() while receive is blocking
		try {
			socket.setSoTimeout(timeout);
			socket.receive(packet);
		}
		catch(SocketTimeoutException e) {
			return null;
		}
		catch (SocketException e) {
			return null;
		}
		
		return packet;
	}

	public void close() {
		if (socket != null)
			socket.close();
	}

}
